home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / text / hyper / hsc_source.lha / source / hsclib / size.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-12  |  11.3 KB  |  365 lines

  1. /*
  2.  * hsclib/size.c
  3.  *
  4.  * evaluate values for WIDTH and HEIGHT from file
  5.  *
  6.  * Copyright (C) 1996  Thomas Aglassinger
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * updated: 27-Jul-1996
  23.  * created:  7-Jan-1996
  24.  */
  25.  
  26. #include "hsclib/inc_base.h"
  27.  
  28. #include "hsclib/uri.h"
  29.  
  30. /* markers for JFIF/JPEG that contain
  31.  * information about image dimension
  32.  */
  33. static UBYTE msof[] =
  34. {
  35.     /* M_SOF0  */ 0xc0,
  36.     /* M_SOF1  */ 0xc1,
  37.     /* M_SOF2  */ 0xc2,
  38.     /* M_SOF3  */ 0xc3,
  39.     /* M_SOF5  */ 0xc5,
  40.     /* M_SOF6  */ 0xc6,
  41.     /* M_SOF7  */ 0xc7,
  42.     /* M_SOF9  */ 0xc9,
  43.     /* M_SOF10 */ 0xca,
  44.     /* M_SOF11 */ 0xcb,
  45.     /* M_SOF13 */ 0xcd,
  46.     /* M_SOF14 */ 0xce,
  47.     /* M_SOF15 */ 0xcf,
  48.     /* end     */ 0x00};
  49.  
  50. /*
  51.  *
  52.  * global funs
  53.  *
  54.  */
  55.  
  56. /*
  57.  * try_set_attr
  58.  *
  59.  * if attribute exists and it's value is empty, set
  60.  * new value and update tag-attribute-string
  61.  */
  62. static VOID try_setattr(HSCPRC * hp, HSCVAR * attr, ULONG value)
  63. {
  64.     if (attr && !get_vartext(attr))
  65.     {
  66.         set_vartext(attr, long2str(value));
  67.  
  68.         /* append attribute name and "=" */
  69.         app_estr(hp->tag_attr_str, " ");
  70.         app_estr(hp->tag_attr_str, attr->name);
  71.         app_estr(hp->tag_attr_str, "=");
  72.  
  73.         /* append quotes and value */
  74.         if ((hp->quotemode == QMODE_KEEP) || (hp->quotemode == QMODE_DOUBLE))
  75.             app_estrch(hp->tag_attr_str, '\"');
  76.         else if (hp->quotemode == QMODE_SINGLE)
  77.             app_estrch(hp->tag_attr_str, '\'');
  78.         app_estr(hp->tag_attr_str, long2str(value));    /* append value */
  79.         if ((hp->quotemode == QMODE_KEEP) || (hp->quotemode == QMODE_DOUBLE))
  80.             app_estrch(hp->tag_attr_str, '\"');
  81.         else if (hp->quotemode == QMODE_SINGLE)
  82.             app_estrch(hp->tag_attr_str, '\'');
  83.  
  84.     }
  85. }
  86.  
  87. /*
  88.  * get_width_height
  89.  *
  90.  * tries to get values for WIDTH and HEIGHT attributes
  91.  * from file
  92.  *
  93.  * result: TRUE, if filetype has been recognised
  94.  */
  95. BOOL get_attr_size(HSCPRC * hp, HSCTAG * tag)
  96. {
  97. #define BUFSIZE  2048
  98. #define WIDTH_PNG  16           /* file indeces for PNG */
  99. #define HEIGHT_PNG 20
  100.  
  101.     HSCVAR *asrc = tag->uri_size;
  102.     STRPTR srcuri = NULL;
  103.  
  104.     if (asrc)
  105.         srcuri = get_vartext(asrc);
  106.     else
  107.     {
  108.         panic("no uri_size");
  109.     }
  110.  
  111.     if (hp->getsize && srcuri && (uri_kind(srcuri) != URI_ext))
  112.     {
  113.         STRARR buf[BUFSIZE];
  114.         EXPSTR *srcpath = init_estr(64);
  115.         EXPSTR *imgpath = init_estr(64);
  116.         ULONG width = 0;
  117.         ULONG height = 0;
  118.         BOOL transparent = FALSE;
  119.         BOOL progressive = FALSE;
  120.         STRPTR filetype = NULL;
  121.         FILE *fref = NULL;      /* file link references to */
  122.         STRARR id_PNG[8] =
  123.         {137, 80, 78, 71, 13, 10, 26, 10};      /* PNG image header */
  124.  
  125.         conv_hscuri2file(hp, srcpath, srcuri);
  126.  
  127.         DSZ(fprintf(stderr, DHL "   uri : \"%s\"\n**    path: \"%s\"\n",
  128.                     srcuri, estr2str(srcpath)));
  129.  
  130.         fref = fopen(estr2str(srcpath), "r");
  131.  
  132.         if (fref)
  133.         {
  134.             /* fill buffer with zero */
  135.             memset(buf, 0, BUFSIZE);
  136.  
  137.             /* read buffer  from file */
  138.             fread(buf, BUFSIZE, 1, fref);
  139.  
  140.             if (buf[0] == 0xff)
  141.             {
  142.                 /*
  143.                  * JFIF/JPEG
  144.                  */
  145.                 BOOL found = FALSE;
  146.                 size_t i = 0;
  147.  
  148.                 /*TODO: progressive */
  149.                 while (!found && (i < BUFSIZE + 8))
  150.                 {
  151.                     if (buf[i] == 0xff)
  152.                     {
  153.                         BOOL is_msof = FALSE;
  154.                         int j = 0;
  155.  
  156.                         DSZ(printf("%04x: %02x %02x: (%02x%02x %02x%02x) ",
  157.                                    (ULONG) i, buf[i], buf[i + 1],
  158.                                    buf[i + 2], buf[i + 3],
  159.                                    buf[i + 4], buf[i + 5]));
  160.  
  161.                         /* check if marker is of required type */
  162.                         while (!is_msof && msof[j])
  163.                             if (buf[i + 1] == msof[j])
  164.                                 is_msof = TRUE;
  165.                             else
  166.                                 j++;
  167.  
  168.                         if (is_msof)
  169.                         {
  170.                             DSZ(
  171.                                    {
  172.                                    for (j = 0; j < 10; j++)
  173.                                    {
  174.  
  175.                                    printf("\n  %-2d: $%02x %-3d",
  176.                                           j, buf[i + j], buf[i + j]);
  177.                                    if (buf[i + j] >= 32)
  178.                                    printf(" '%c'", buf[i + j]);
  179.  
  180.                                    }
  181.                                    }
  182.                             );
  183.  
  184.                             filetype = "JFIF/JPEG";
  185.                             width = buf[i + 8] + (buf[i + 7] << 8);
  186.                             height = buf[i + 6] + (buf[i + 5] << 8);
  187.                             found = TRUE;
  188.  
  189.                         }
  190.                         else
  191.                         {
  192.                             DDA(printf("ignore\n"));
  193.                         }
  194.                     }
  195.  
  196.                     i++;
  197.                 }
  198.  
  199.                 /* check if buffer exeeds */
  200.                 if (i >= (BUFSIZE + 8))
  201.                 {
  202.                     panic("image buffer exeeds");
  203.                 }
  204.             }
  205.             else if (!strncmp("GIF87a", buf, 6)
  206.                      || !strncmp("GIF89a", buf, 6))
  207.             {
  208.                 /*
  209.                  * GIF
  210.                  */
  211.                 LONG use_global_colormap = (buf[10] & 0x80) >> 7;
  212.                 LONG pixeldepth = (buf[10] & 0x07) + 1;
  213.                 LONG startimg =
  214.                 13 + use_global_colormap * 3 * (1 << pixeldepth);
  215.                 BOOL fucked_up = FALSE;
  216.  
  217.                 while (!fucked_up && (buf[startimg] != ','))
  218.                 {
  219.                     if (buf[startimg] == '!')
  220.                     {
  221.                         UBYTE blksize = 0;
  222.  
  223.                         if (buf[startimg + 1] == 0xF9)
  224.                         {
  225.                             /* graphic control extensions */
  226.                             /* check if transparent */
  227.                             transparent = (buf[startimg + 3] & 0x01);
  228.  
  229.                             DDA(
  230.                                    {
  231.                                    if (transparent)
  232.                                    fprintf(stderr, DHL "  (transparent)\n");
  233.                                    }
  234.                             );
  235.                         }
  236.  
  237.                         /* skip all blocks */
  238.                         startimg += 2;
  239.                         do
  240.                         {
  241.                             blksize = buf[startimg];
  242.                             DDA(printf("  skip block sized %d\n", blksize));
  243.                             startimg += 1L + blksize;
  244.                         }
  245.                         while (!fucked_up && (blksize));
  246.  
  247.                         /* check if buffer exeeds */
  248.                         if (startimg > (BUFSIZE + 9))
  249.                         {
  250.                             panic("image buffer exeeds");
  251.                             fucked_up = TRUE;
  252.                         }
  253.  
  254.                     }
  255.                     else
  256.                     {
  257.                         panic("unknown gif-block");
  258.                         fucked_up = TRUE;
  259.                     }
  260.                 }
  261.  
  262.                 if ((buf[startimg] != ',') && !fucked_up)
  263.                 {
  264.                     panic("didn't find image separator");
  265.                 }
  266.                 else
  267.                 {
  268.                     /* been sucessful */
  269.                     filetype = "GIF";
  270.                     width = buf[startimg + 5] + 256 * buf[startimg + 6];
  271.                     height = buf[startimg + 7] + 256 * buf[startimg + 8];
  272.                     progressive = (0 != (buf[startimg + 9] & (1 << 6)));
  273.                     DDA(fprintf(stderr, DHL "  width : %lu\nheight: %lu\n",
  274.                                 width, height));
  275.                 }
  276.             }
  277.             else if (!strncmp(id_PNG, buf, 8))
  278.             {
  279.                 /*
  280.                  * PNG
  281.                  */
  282.                 filetype = "PNG";
  283.                 width = 0x00800000 * buf[WIDTH_PNG] +
  284.                     0x00010000 * buf[WIDTH_PNG + 1] +
  285.                     0x00000100 * buf[WIDTH_PNG + 2] +
  286.                     0x00000001 * buf[WIDTH_PNG + 3];
  287.                 height = 0x00800000 * buf[HEIGHT_PNG] +
  288.                     0x00010000 * buf[HEIGHT_PNG + 1] +
  289.                     0x00000100 * buf[HEIGHT_PNG + 2] +
  290.                     0x00000001 * buf[HEIGHT_PNG + 3];
  291.  
  292.                 progressive = buf[HEIGHT_PNG + 9];
  293.                 /*TODO: transparent */
  294.  
  295. #if DEBUG_SIZE
  296.                 if (hp->debug)
  297.                 {
  298.                     int i;
  299.                     for (i = 0; i < BUFSIZE; i++)
  300.                     {
  301.  
  302.                         fprintf(stderr, "%-2d: $%02x %-3d", i, buf[i], buf[i]);
  303.                         if (buf[i] >= 32)
  304.                             fprintf(stderr, " '%c'\n", buf[i]);
  305.                         else
  306.                             fprintf(stderr, "\n");
  307.  
  308.                     }
  309.                 }
  310. #endif
  311.                 DDA(fprintf(stderr, DHL "  width : %lu\nheight: %lu\n",
  312.                             width, height));
  313.             }
  314.             else
  315.             {
  316.                 /* unknown file type */
  317.                 hsc_message(hp, MSG_UNKN_FILETYPE,
  318.                             "filetype of %q not recognised",
  319.                             estr2str(srcpath));
  320.             }
  321.  
  322.             DSZ(fprintf(stderr, DHL "  size: \"%s\" (%ldx%ld)\n",
  323.                         filetype, width, height));
  324.  
  325.             fclose(fref);
  326.         }
  327.         else
  328.         {
  329.             DSZ(fprintf(stderr, DHL "  Can't open image `%s'\n",
  330.                         estr2str(srcpath)));
  331.             hsc_msg_nouri(hp, estr2str(srcpath), srcuri, "image-size");
  332.         }
  333.  
  334.         /* set values */
  335.         if (height && width)
  336.         {
  337.             HSCVAR *awidth = find_varname(tag->attr, "WIDTH");
  338.             HSCVAR *aheight = find_varname(tag->attr, "HEIGHT");
  339.  
  340.             /* status message */
  341.             app_estr(srcpath, ": ");
  342.             app_estr(srcpath, filetype);
  343.             app_estr(srcpath, ", ");
  344.             app_estr(srcpath, long2str(width));
  345.             app_estr(srcpath, "x");
  346.             app_estr(srcpath, long2str(height));
  347.             if (progressive)
  348.                 app_estr(srcpath, ", progressive");
  349.             if (transparent)
  350.                 app_estr(srcpath, ", transparent");
  351.             hsc_status_misc(hp, estr2str(srcpath));
  352.  
  353.             try_setattr(hp, awidth, width);
  354.             try_setattr(hp, aheight, height);
  355.         }
  356.  
  357.         /* free local resources */
  358.         del_estr(srcpath);
  359.         del_estr(imgpath);
  360.     }
  361.  
  362.     return (TRUE);
  363. }
  364.  
  365.